package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.swing.text.AttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import org.apache.jackrabbit.j2ee.RepositoryAccessServlet;
import org.apache.jackrabbit.util.Text;

public final class populate_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {



    public static final List DEFAULT_TYPES = Arrays.asList(
            new String[]{"pdf", "rtf", "doc", "ppt", "xls"});

    public static class Search {

        private final String filetype;

        private final String term;

        private final int start;

        public Search(String filetype, String term, int start) {
            this.filetype = filetype;
            this.term = term;
            this.start = start;
        }

        public URL[] getURLs() throws Exception {
            List urls = new ArrayList();
            String query = term + " filetype:" + filetype;
            URL google = new URL("http://www.google.com/search?q=" +
                    URLEncoder.encode(query, "UTF-8") + "&start=" + start);
            URLConnection con = google.openConnection();
            con.setRequestProperty("User-Agent", "");
            InputStream in = con.getInputStream();
            try {
                HTMLEditorKit kit = new HTMLEditorKit();
                HTMLDocument doc = new HTMLDocument();
                doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
                kit.read(new InputStreamReader(in, "UTF-8"), doc, 0);
                HTMLDocument.Iterator it = doc.getIterator(HTML.Tag.A);
                while (it.isValid()) {
                    AttributeSet attr = it.getAttributes();
                    if (attr != null) {
                        String href = (String) attr.getAttribute(HTML.Attribute.HREF);
                        if (href != null && href.endsWith("." + filetype)) {
                            URL url = new URL(new URL("http", "www.google.com", "dummy"), href);
                            if (url.getHost().indexOf("google") == -1) {
                                urls.add(url);
                            }
                        }
                    }
                    it.next();
                }
            } finally {
                in.close();
            }
            return (URL[]) urls.toArray(new URL[urls.size()]);
        }
    }

    public static class ProgressInputStream extends FilterInputStream {

        private final int length;

        private final String fileName;

        private final String varName;

        private final JspWriter out;

        private long read;

        private long nextReport = (16 * 1024);

        public ProgressInputStream(InputStream in, int length, String fileName,
                                   String varName, JspWriter out) {
            super(in);
            this.length = length;
            this.fileName = fileName;
            this.varName = varName;
            this.out = out;
        }

        public int read() throws IOException {
            int r = super.read();
            reportProgress(r);
            return r;
        }

        public int read(byte b[]) throws IOException {
            int r = super.read(b);
            reportProgress(r);
            return r;
        }

        public int read(byte b[], int off, int len) throws IOException {
            int r = super.read(b, off, len);
            reportProgress(r);
            return r;
        }

        private void reportProgress(int r) throws IOException {
            if (r != -1) {
                read += r;
                if (read > nextReport || read == length) {
                    // report every 16k
                    synchronized (out) {
                        double s = 1000d * (double) read / (double) length;
                        out.println("<script>" + varName + ".inform(" +
                                Math.min((int) Math.ceil(s), 1000) +
                                ", '" + Text.encodeIllegalXMLCharacters(fileName) + "')</script>");
                        out.flush();
                    }
                    nextReport += (16 * 1024);
                }
            }
        }
    }

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;


    Repository rep;
    Session jcrSession;
    String wspName;
    try {
        rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext());
        jcrSession = rep.login(new SimpleCredentials("user", "".toCharArray()));
        wspName = jcrSession.getWorkspace().getName();
    } catch (Throwable e) {
        
      out.write("Error while accessing the repository: <font color=\"red\">");
      out.print( Text.encodeIllegalXMLCharacters(e.getMessage()) );
      out.write("</font><br>");

        
      out.write("Check the configuration or use the <a href=\"admin/\">easy setup</a> wizard.");

        return;
    }
    try {
        String seedWord = request.getParameter("seed");
        if (seedWord != null) {
            seedWord = new String(seedWord.getBytes("ISO-8859-1"), "UTF-8");
        }
        int numDocs = 0;
        List filetypes = new ArrayList();
        if (request.getParameter("num") != null) {
            try {
                numDocs = Integer.parseInt(request.getParameter("num"));
            } catch (NumberFormatException e) {
                // ignore
            }
        }
        String[] types = request.getParameterValues("filetype");
        if (types != null) {
            filetypes.addAll(Arrays.asList(types));
        } else {
            filetypes = DEFAULT_TYPES;
        }

if (seedWord != null && numDocs > 0 && filetypes.size() > 0) { 
      out.write("\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("<title>Welcome to Apache Jackrabbit - Populate workspace: ");
      out.print( Text.encodeIllegalXMLCharacters(wspName) );
      out.write("</title>\n");
      out.write("<link rel=\"shortcut icon\" href=\"");
      out.print( Text.encodeIllegalXMLCharacters(request.getContextPath()) );
      out.write("/images/favicon.ico\" type=\"image/vnd.microsoft.icon\">\n");
      out.write("<style type=\"text/css\" media=\"all\">\n");
      out.write("      @import url(\"");
      out.print( Text.encodeIllegalXMLCharacters(request.getContextPath()) );
      out.write("/css/default.css\");\n");
      out.write("</style>\n");
      out.write("<script><!--\n");
      out.write("function draw() {\n");
      out.write("\t// draw the bar\n");
      out.write("        document.write('<table cellspacing=\"0\" cellpadding=\"0\" style=\"border-color:' + this.borderColor + '; border-width:' + this.borderWidth + '; border-style:' + this.borderStyle + '\">');\n");
      out.write("        document.write('<tr><td>');\n");
      out.write("        document.write('<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"\">');\n");
      out.write("        document.write('<tr><td style=\"background-color:' + this.barColor +'\"><img src=\"");
      out.print( Text.encodeIllegalXMLCharacters(request.getContextPath()) );
      out.write("/images/0.gif\" id=\"' + this.id + 'barFG\" width=\"0\" height=\"' + this.height + '\"/></td>');\n");
      out.write("        document.write('<td><img src=\"");
      out.print( Text.encodeIllegalXMLCharacters(request.getContextPath()) );
      out.write("/images/0.gif\" id=\"' + this.id + 'barBG\" width=\"' + this.width + '\" height=\"' + this.height + '\"/></td></tr>');\n");
      out.write("        document.write('</table>');\n");
      out.write("        document.write('</tr></td>');\n");
      out.write("        document.write('</table>');\n");
      out.write("        document.write('<table>');\n");
      out.write("        document.write('<tr><td><img src=\"");
      out.print( Text.encodeIllegalXMLCharacters(request.getContextPath()) );
      out.write("/images/0.gif\" width=\"' + this.width + '\" height=\"0\"/></td></tr>');\n");
      out.write("        document.write('<tr><td align=\"center\"><span id=\"' + this.id + 'barValue\">0%</span></td></tr>');\n");
      out.write("        document.write('<tr><td align=\"center\"><span id=\"' + this.id + 'barInfo\">&nbsp;</span></td></tr>');\n");
      out.write("        document.write('</table>');\n");
      out.write("\n");
      out.write("\tthis.barFG = document.getElementById(this.id + 'barFG');\n");
      out.write("\tthis.barBG = document.getElementById(this.id + 'barBG');\n");
      out.write("\tthis.barValue = document.getElementById(this.id + 'barValue').firstChild;\n");
      out.write("\tthis.barInfo = document.getElementById(this.id + 'barInfo').firstChild;\n");
      out.write("}\n");
      out.write("\n");
      out.write("// informs the progress bar about the current value\n");
      out.write("function inform(value, info) {\n");
      out.write("\tvar barWidth = Math.floor(this.width * value / this.maxValue);\n");
      out.write("\tvar spaceWidth = this.width - barWidth;\n");
      out.write("\tvar perCent = Math.floor(100 * value / this.maxValue);\n");
      out.write("\tthis.barFG.width = barWidth;\n");
      out.write("\tthis.barBG.width = spaceWidth;\n");
      out.write("\tthis.barValue.nodeValue = perCent + '%';\n");
      out.write("\tthis.barInfo.nodeValue = info;\n");
      out.write("}\n");
      out.write("\n");
      out.write("// constructor\n");
      out.write("function ProgressBar(maxValue, width, height) {\n");
      out.write("\tthis.maxValue = maxValue;\n");
      out.write("\tthis.width = width;\n");
      out.write("\tthis.height = height;\n");
      out.write("\tthis.id = '' + Math.round(Math.random() * 10000);\n");
      out.write("\tthis.inform = inform;\n");
      out.write("\tthis.draw = draw;\n");
      out.write("}\n");
      out.write("\n");
      out.write("// default values\n");
      out.write("ProgressBar.prototype.barColor = \"green\";\n");
      out.write("ProgressBar.prototype.borderColor = \"grey\";\n");
      out.write("ProgressBar.prototype.borderStyle = \"groove\";\n");
      out.write("ProgressBar.prototype.borderWidth = \"2px\";\n");
      out.write("\n");
      out.write("// -->\n");
      out.write("</script>\n");
      out.write("</head>\n");
      out.write("  <body>\n");
      out.write("  <div style=\"background: white; border: 1px solid black; padding: 50px; width: 510px; margin: 50px auto;\">\n");
      out.write("  <h2>Populate workspace: \"");
      out.print( Text.encodeIllegalXMLCharacters(wspName) );
      out.write("\"</h2><br>\n");
      out.write("    <p>Overall progress</p>\n");
      out.write("    <script>var pb = new ProgressBar(");
      out.print( numDocs );
      out.write(", 500, 30);pb.draw();</script>\n");
      out.write("    \n");
      out.write("    <p>Downloading document</p>\n");
      out.write("    <script>var dp = new ProgressBar(1000, 500, 30);dp.draw();</script>\n");
      out.write("    ");

            Node root = jcrSession.getRootNode();
            int n = 0;
            for (int typeIdx = 0; typeIdx < filetypes.size(); typeIdx++) {
                String type = (String) filetypes.get(typeIdx);
                int offset = 0;
                while (n < numDocs * (typeIdx + 1) / filetypes.size()) {
                    final URL[] urls = new Search(type, seedWord, offset).getURLs();
                    if (urls.length == 0) {
                        break;
                    }
                    for (int i = 0; i < urls.length; i++) {
                        final URL currentURL = urls[i];
                        String path = urls[i].getPath();
                        if (path.startsWith("/")) {
                            path = path.substring(1);
                        }
                        final String host = urls[i].getHost();
                        List folderNames = new ArrayList();
                        folderNames.addAll(Arrays.asList(host.split("\\.")));
                        Collections.reverse(folderNames);
                        folderNames.addAll(Arrays.asList(path.split("/", 0)));
                        final String fileName = URLDecoder.decode((String) folderNames.remove(folderNames.size() - 1), "UTF-8").replaceAll(":", "_");
                        Node node = root;
                        for (Iterator fn = folderNames.iterator(); fn.hasNext(); ) {
                            String name = URLDecoder.decode((String) fn.next(), "UTF-8");
                            name = name.replaceAll(":", "_");
                            if (name.length() == 0) {
                                continue;
                            }
                            if (!node.hasNode(name)) {
                                node.addNode(name, "nt:folder");
                            }
                            node = node.getNode(name);
                        }
                        if (!node.hasNode(fileName)) {
                            final JspWriter fOut = out;
                            Node file = node.addNode(fileName, "nt:file");
                            final Node resource = file.addNode("jcr:content", "nt:resource");
                            final Exception[] ex = new Exception[1];
                            Thread t = new Thread(new Runnable() {
                                public void run() {
                                    try {
                                        String info = fileName + " (" + host + ")";
                                        URLConnection con = currentURL.openConnection();
                                        InputStream in = con.getInputStream();
                                        try {
                                            synchronized (fOut) {
                                                fOut.println("<script>dp.inform(0, '" + Text.encodeIllegalXMLCharacters(info) + "')</script>");
                                                fOut.flush();
                                            }
                                            int length = con.getContentLength();
                                            if (length != -1) {
                                                in = new ProgressInputStream(in, length, info, "dp", fOut);
                                            }
                                            resource.setProperty("jcr:data", in);
                                            String mimeType = URLConnection.guessContentTypeFromName(fileName);
                                            if (mimeType == null) {
                                                if (fileName.endsWith(".doc")) {
                                                    mimeType = "application/msword";
                                                } else if (fileName.endsWith(".xls")) {
                                                    mimeType = "application/vnd.ms-excel";
                                                } else if (fileName.endsWith(".ppt")) {
                                                    mimeType = "application/mspowerpoint";
                                                } else {
                                                    mimeType = "application/octet-stream";
                                                }
                                            }
                                            resource.setProperty("jcr:mimeType", mimeType);
                                            Calendar lastModified = Calendar.getInstance();
                                            lastModified.setTimeInMillis(con.getLastModified());
                                            resource.setProperty("jcr:lastModified", lastModified);
                                        } finally {
                                            in.close();
                                        }
                                    } catch (Exception e) {
                                        ex[0] = e;
                                    }
                                }
                            });
                            t.start();
                            for (int s = 0; t.isAlive(); s++) {
                                Thread.sleep(100);
                                if (s % 10 == 0) {
                                    synchronized (fOut) {
                                        fOut.println("<script>pb.inform(" + n + ", '')</script>");
                                        fOut.flush();
                                    }
                                }
                            }
                            if (ex[0] == null) {
                                jcrSession.save();
                                n++;
                                synchronized (fOut) {
                                    fOut.println("<script>pb.inform(" + n + ", '')</script>");
                                    fOut.flush();
                                }
                                if (n >= numDocs * (typeIdx + 1) / filetypes.size()) {
                                    break;
                                }
                            } else {
                                jcrSession.refresh(false);
                            }
                        }
                    }
                    offset += 10;
                }
            }

      out.write("  </div>\n");
      out.write("  </body>\n");
      out.write("</html>\n");
 } else {
request.setAttribute("title", "Populate workspace " + wspName);

      org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "header.jsp", out, false);
      out.write("\n");
      out.write("<p>\n");
      out.write("  This page allows you to populate the workspace with documents downloaded\n");
      out.write("  from the Internet.\n");
      out.write("</p>\n");
      out.write("    <form method=\"POST\">\n");
      out.write("      <table>\n");
      out.write("      <tr><td>Seed word (optional):</td><td><input name=\"seed\" type=\"text\" size=\"30\" value=\"");
      out.print( seedWord == null ? "" : Text.encodeIllegalXMLCharacters(seedWord) );
      out.write("\"/></td></tr>\n");
      out.write("      <tr><td>Number of documents:</td><td><input name=\"num\" type=\"text\" size=\"30\" value=\"");
      out.print( numDocs == 0 ? 100 : numDocs );
      out.write("\"/></td></tr>\n");
      out.write("      <tr valign=\"top\"><td>Document types:</td><td><input name=\"filetype\" type=\"checkbox\" value=\"pdf\" ");
      out.print( filetypes.contains("pdf") ? "checked" : "" );
      out.write("/> Adobe Acrobat PDF<br/><input name=\"filetype\" type=\"checkbox\" value=\"rtf\" ");
      out.print( filetypes.contains("rtf") ? "checked" : "" );
      out.write("/> Rich Text Format<br/><input name=\"filetype\" type=\"checkbox\" value=\"doc\" ");
      out.print( filetypes.contains("doc") ? "checked" : "" );
      out.write("/> Microsoft Word<br/><input name=\"filetype\" type=\"checkbox\" value=\"ppt\" ");
      out.print( filetypes.contains("ppt") ? "checked" : "" );
      out.write("/> Microsoft PowerPoint<br/><input name=\"filetype\" type=\"checkbox\" value=\"xls\" ");
      out.print( filetypes.contains("xls") ? "checked" : "" );
      out.write("/> Microsoft Excel<br/></td></tr>\n");
      out.write("      <tr><td>&nbsp;</td><td><input type=\"submit\" value=\"Populate!\"/></td></tr>\n");
      out.write("      </table>\n");
      out.write("    </form>\n");
      org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "footer.jsp", out, false);
      out.write('\n');
    }
    } finally {
        if (jcrSession != null) {
            jcrSession.logout();
        }
    }

      out.write('\n');
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
